/**  
* @Title: BaseCacheKeyGenerator.java
* @Package com.lemon.conf.redis
* @Description: (一句话阐述):
* @author Ran_cc
* @date 2018年5月30日
* @version V1.0  
*/
package com.lemon.conf.redis.custom;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.stereotype.Component;

import com.lemon.utils.MD5;

/**
 * <p>
 * Title:重写key的生成策略
 * </p>
 * <p>
 * Description:
 * 重写之后刷新指定的key 会找不到, 这样需要在切面里面判断注解key是不是自定义的key策略<br>
 * 重新生成key保存在要刷新的集合里面,这样传过来的key就能和监控的key对应上了<br>
 * 生成的key用md5加密, 这样key占用的空间就非常小了
 * </p>
 * <p>
 * Company:
 * </p>
 * 
 * @author Ran_cc
 * @date 2018年5月30日
 * @版本 V 1.0
 */
@Component( "keyGenerator" )
public class BaseCacheKeyGenerator implements KeyGenerator {

	@Override
	public Object generate( Object target, Method method, Object ... params ) {
		Object key = new BaseCacheKey(target, method, params);
		String md5 = MD5.getMD5(key.toString());
		return md5;
	}


	

	

	
	
	
}

class BaseCacheKey implements Serializable {

	private static final long serialVersionUID = -1651889717223143579L;

	private static final Logger logger = LoggerFactory.getLogger(BaseCacheKey.class);

	private final Object [] params;
	private final int hashCode;
	private final String className;
	private final String methodName;

	public BaseCacheKey( Object target, Method method, Object [] elements ) {
		//this.className = target.getClass().getName();
		this.className = method.getDeclaringClass().getName();
		this.methodName = getMethodName(method);
		this.params = new Object [elements.length];
		System.arraycopy(elements, 0, this.params, 0, elements.length);
		this.hashCode = generatorHashCode();
	}

	private String getMethodName( Method method ) {
		StringBuilder builder = new StringBuilder(method.getName());
		Class<?> [] types = method.getParameterTypes();
		if (types.length != 0) {
			builder.append("(");
			for (Class<?> type : types) {
				String name = type.getName();
				builder.append(name + ",");
			}
			builder.append(")");
		}
		return builder.toString();
	}

	@Override
	public boolean equals( Object obj ) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		BaseCacheKey o = (BaseCacheKey) obj;
		if (this.hashCode != o.hashCode())
			return false;
		if (!Optional.ofNullable(o.className).orElse("").equals(this.className))
			return false;
		if (!Optional.ofNullable(o.methodName).orElse("").equals(this.methodName))
			return false;
		if (!Arrays.equals(params, o.params))
			return false;
		return true;
	}

	@Override
	public final int hashCode() {
		return hashCode;
	}

	private int generatorHashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + hashCode;
		result = prime * result + ((methodName == null) ? 0 : methodName.hashCode());
		result = prime * result + Arrays.deepHashCode(params);
		result = prime * result + ((className == null) ? 0 : className.hashCode());
		return result;
	}

	@Override
	public String toString() {
		logger.debug(Arrays.toString(params));
		logger.debug(Arrays.deepToString(params));
		return "keyGenerator [params=" + Arrays.deepToString(params) + ", className=" + className + ", methodName="
				+ methodName + "]";
	}

}
